package com.audaque.springboot.foshanupload.security.filter;

import cn.hutool.json.JSONUtil;
import com.audaque.springboot.foshanupload.authcore.model.currentUser.TransmittableThreadLocalCurrentUser;
import com.audaque.springboot.foshanupload.core.properties.SwitchProperties;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author zgb
 * @desc 自定义账号密码认证过滤器
 * @date 2022-08-05 17:44:42
 */
@Data
@NoArgsConstructor
@Slf4j
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    @Autowired
    private SwitchProperties switchProperties;


    @SneakyThrows
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //判断是否是JSON登录
        String contentType = request.getContentType();
        if (MediaType.APPLICATION_JSON_UTF8_VALUE.equalsIgnoreCase(contentType)
                || "application/json; charset=UTF-8".equalsIgnoreCase(contentType)
                || MediaType.APPLICATION_JSON_VALUE.equals(contentType)) {

            //获取提交的JSON数据
            ServletInputStream ris = request.getInputStream();
            StringBuilder content = new StringBuilder();
            byte[] b = new byte[1024];
            int lens;
            while ((lens = ris.read(b)) > 0) {
                content.append(new String(b, 0, lens));
            }
            //从JSON数据中获取用户名和密码

            TransmittableThreadLocalCurrentUser transmittableThreadLocalCurrentUser = JSONUtil.toBean(content.toString(), TransmittableThreadLocalCurrentUser.class);
            String username = transmittableThreadLocalCurrentUser.getUsername();
            String password = transmittableThreadLocalCurrentUser.getPassword();


            //parameterMap中参数的方法是加了锁的，无法直接修改，需先将锁打开，再做操作，操作后记得关上
            Map<String, String[]> parameterMap = request.getParameterMap();
            Method method = parameterMap.getClass().getMethod("setLocked",
                    new Class[]{boolean.class});
            //打开锁
            method.invoke(parameterMap, new Object[]{new Boolean(false)});
            //从body转发到request parameterMap
            parameterMap.put("username", new String[]{username});
            parameterMap.put("password", new String[]{password});

            //关锁
            method.invoke(parameterMap, new Object[]{new Boolean(true)});


        }
        //去执行表单登录
        return super.attemptAuthentication(request, response);
    }

}
